@cachly-dev/mcp-server 0.10.228 → 0.10.229

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- const s=new Set;let u=!1;function l(){u=!0}function f(e){if(e instanceof Error)return(e.message||e.name||"Error").slice(0,200);if(typeof e=="string")return e.slice(0,200)||"leerer Text geworfen";if(e===void 0)return"undefined geworfen (kein Grund mitgegeben)";if(e===null)return"null geworfen (kein Grund mitgegeben)";try{const n=JSON.stringify(e);return n&&n!=="{}"?n.slice(0,200):`${typeof e} ohne Inhalt geworfen`}catch{return`${typeof e} geworfen, nicht darstellbar`}}function c(e,n){return s.has(e)?!1:(s.add(e),u||console.error(`[aussetzer] ${e}: ${n}`),!0)}function h(e){return s.has(e)}function g(){return[...s]}function E(){s.clear(),u=!1}const m="bedeutung-ohne-vektoren",p="bedeutung-ohne-dienst",x="bedeutung-ohne-fragevektor",d="bedeutung-abbruch",z="einbettung-beim-schreiben",k="versuch-laeuft-leer",a="cachly:aussetzer:",i=720*60*60;async function y(e,n,o){const r=c(n,o);if(!e)return r;try{const t=`${a}${n}`;await e.hincrby(t,"anzahl",1),await e.hset(t,{zuletzt:new Date().toISOString(),text:o.slice(0,500)}),await e.expire(t,i)}catch(t){c(`${n}-vermerk`,`der Aussetzer liess sich nicht vermerken (${t instanceof Error?t.message:String(t)}) \u2014 er steht nur in diesem Protokoll und ist nach einem Neustart weg`)}return r}async function S(e){if(!e)return null;try{const n=await e.keys(`${a}*`),o=[];for(const r of n){const t=await e.hgetall(r);!t||!t.anzahl||o.push({grund:r.slice(a.length),anzahl:Number(t.anzahl)||0,zuletzt:t.zuletzt??"",text:t.text??""})}return o.sort((r,t)=>t.anzahl-r.anzahl||r.grund.localeCompare(t.grund)),o}catch{return null}}export{i as AUSSETZER_TTL_SEKUNDEN,a as AUSSETZER_VORSATZ,p as OHNE_DIENST,x as OHNE_FRAGEVEKTOR,z as OHNE_SCHREIBVEKTOR,m as OHNE_VEKTOREN,d as SINNPFAD_ABBRUCH,k as VERSUCH_LEER,l as aussetzerLeise,f as fehlerText,g as gemeldeteGruende,S as leseVermerke,c as meldeEinmal,y as meldeUndVermerke,h as schonGemeldet,E as setzeAussetzerZurueck};
1
+ const o=new Set;let a=!1;function x(){a=!0}function b(e){if(e instanceof Error)return(e.message||e.name||"Error").slice(0,200);if(typeof e=="string")return e.slice(0,200)||"leerer Text geworfen";if(e===void 0)return"undefined geworfen (kein Grund mitgegeben)";if(e===null)return"null geworfen (kein Grund mitgegeben)";try{const n=JSON.stringify(e);return n&&n!=="{}"?n.slice(0,200):`${typeof e} ohne Inhalt geworfen`}catch{return`${typeof e} geworfen, nicht darstellbar`}}function c(e,n){return o.has(e)?!1:(o.add(e),a||console.error(`[aussetzer] ${e}: ${n}`),!0)}function p(e){return o.has(e)}function E(){return[...o]}function y(){o.clear(),a=!1}const i="bedeutung-ohne-vektoren",l="bedeutung-ohne-dienst",f="bedeutung-ohne-fragevektor",h="bedeutung-abbruch",d="einbettung-beim-schreiben",g="versuch-laeuft-leer",u="cachly:aussetzer:";function z(e){switch(e){case i:return"no stored vectors, so search by meaning could not run";case l:return"embedding service not reachable, so search by meaning could not run";case f:return"the question could not be embedded, so that search used words only";case h:return"search by meaning failed unexpectedly, so that search used words only";case d:return"embedding failed while saving a lesson; the lesson is saved but not findable by meaning";case g:return"an experiment is switched on but has no effect";default:return e}}function w(e){const n=String(e??""),s=n.indexOf("("),r=n.lastIndexOf(")");return s>=0&&r>s+1?n.slice(s+1,r).slice(0,140):""}const m=720*60*60;async function k(e,n,s){const r=c(n,s);if(!e)return r;try{const t=`${u}${n}`;await e.hincrby(t,"anzahl",1),await e.hset(t,{zuletzt:new Date().toISOString(),text:s.slice(0,500)}),await e.expire(t,m)}catch(t){c(`${n}-vermerk`,`der Aussetzer liess sich nicht vermerken (${t instanceof Error?t.message:String(t)}) \u2014 er steht nur in diesem Protokoll und ist nach einem Neustart weg`)}return r}async function S(e){if(!e)return null;try{const n=await e.keys(`${u}*`),s=[];for(const r of n){const t=await e.hgetall(r);!t||!t.anzahl||s.push({grund:r.slice(u.length),anzahl:Number(t.anzahl)||0,zuletzt:t.zuletzt??"",text:t.text??""})}return s.sort((r,t)=>t.anzahl-r.anzahl||r.grund.localeCompare(t.grund)),s}catch{return null}}export{m as AUSSETZER_TTL_SEKUNDEN,u as AUSSETZER_VORSATZ,l as OHNE_DIENST,f as OHNE_FRAGEVEKTOR,d as OHNE_SCHREIBVEKTOR,i as OHNE_VEKTOREN,h as SINNPFAD_ABBRUCH,g as VERSUCH_LEER,w as aussetzerEinzelheit,z as aussetzerErklaerung,x as aussetzerLeise,b as fehlerText,E as gemeldeteGruende,S as leseVermerke,c as meldeEinmal,k as meldeUndVermerke,p as schonGemeldet,y as setzeAussetzerZurueck};
@@ -1 +1 @@
1
- import{existsSync as g,readFileSync as l}from"node:fs";import{dirname as f,join as p}from"node:path";import{fileURLToPath as d}from"node:url";const o={version:"unbekannt",commit:"unbekannt",gebautAm:"unbekannt"};function k(t){if(typeof t!="object"||t===null)return!1;const e=t;return typeof e.version=="string"&&typeof e.commit=="string"&&typeof e.gebautAm=="string"}function A(t=f(d(import.meta.url))){const e=p(t,"bauabdruck-daten.generiert.json");if(!g(e))return o;try{const n=JSON.parse(l(e,"utf-8"));return k(n)?n:o}catch{return o}}const y=A(),i=14;function T(t,e=new Date){const n=new Date(t);return Number.isNaN(n.getTime())?!1:(e.getTime()-n.getTime())/864e5>i}function B(t,e=new Date){if(t.gebautAm==="unbekannt")return"\u2754 **Bauabdruck: unbekannt** \u2014 noch kein `npm run build` gelaufen, Version/Commit nicht feststellbar";const n=new Date(t.gebautAm),r=!Number.isNaN(n.getTime()),u=r&&T(t.gebautAm,e),a=r?Math.floor((e.getTime()-n.getTime())/864e5):null,m=a===null?"":` (vor ${a} Tag${a===1?"":"en"})`,s=u?"\u{1F7E1}":"\u2705",c=u?` \u2014 laeuft laenger als ${i} Tage. Kein Fehler, aber sichtbar.`:"",b=r?t.gebautAm.slice(0,10):t.gebautAm;return`${s} **Bauabdruck:** v${t.version} \xB7 commit \`${t.commit}\` \xB7 gebaut am ${b}${m}${c}`}export{i as ALTER_SCHWELLE_TAGE,o as RUECKFALL_BAUABDRUCK,y as bauabdruck,B as formatiereBauabdruck,T as istAlt,A as ladeBauabdruck};
1
+ import{existsSync as g,readFileSync as f}from"node:fs";import{dirname as l,join as d}from"node:path";import{fileURLToPath as p}from"node:url";const u={version:"unbekannt",commit:"unbekannt",gebautAm:"unbekannt"};function A(t){if(typeof t!="object"||t===null)return!1;const e=t;return typeof e.version=="string"&&typeof e.commit=="string"&&typeof e.gebautAm=="string"}function k(t=l(p(import.meta.url))){const e=d(t,"bauabdruck-daten.generiert.json");if(!g(e))return u;try{const n=JSON.parse(f(e,"utf-8"));return A(n)?n:u}catch{return u}}const w=k(),a=14;function T(t,e=new Date){const n=new Date(t);return Number.isNaN(n.getTime())?!1:(e.getTime()-n.getTime())/864e5>a}function N(t,e=new Date){if(t.gebautAm==="unbekannt")return"\u2754 **Build: unknown** \u2014 no `npm run build` has run, so version and commit cannot be told";const n=new Date(t.gebautAm),o=!Number.isNaN(n.getTime()),i=o&&T(t.gebautAm,e),r=o?Math.floor((e.getTime()-n.getTime())/864e5):null,m=r===null?"":` (${r} day${r===1?"":"s"} ago)`,s=i?"\u{1F7E1}":"\u2705",c=i?` \u2014 running for more than ${a} days. Not an error, but worth knowing.`:"",b=o?t.gebautAm.slice(0,10):t.gebautAm;return`${s} **Build:** v${t.version} \xB7 commit \`${t.commit}\` \xB7 built ${b}${m}${c}`}export{a as ALTER_SCHWELLE_TAGE,u as RUECKFALL_BAUABDRUCK,w as bauabdruck,N as formatiereBauabdruck,T as istAlt,k as ladeBauabdruck};
@@ -1,5 +1,5 @@
1
- import{existsSync as c}from"node:fs";import{readFile as u,writeFile as f}from"node:fs/promises";import{resolve as a}from"node:path";import{installClsPostCommitHook as h}from"./cls-hook.js";import{instanzIdFuerSkript as m}from"./git-ohne-shell.js";const s=/(?:#!\/bin\/sh\n)?# cachly brain_watch[\s\S]*?\nexit 0\n?/;function p(r){if(!s.test(r))return null;let t=r;for(let n=s.exec(t);n;n=s.exec(t)){const o=t.slice(0,n.index).replace(/\s+$/,""),i=t.slice(n.index+n[0].length).replace(/^\s*\n/,"");t=o+(o&&i.trim()?`
1
+ import{existsSync as c}from"node:fs";import{readFile as u,writeFile as f}from"node:fs/promises";import{resolve as a}from"node:path";import{gitHookOrdner as m,installClsPostCommitHook as h}from"./cls-hook.js";import{instanzIdFuerSkript as p}from"./git-ohne-shell.js";const l=/(?:#!\/bin\/sh\n)?# cachly brain_watch[\s\S]*?\nexit 0\n?/;function d(r){if(!l.test(r))return null;let t=r;for(let n=l.exec(t);n;n=l.exec(t)){const o=t.slice(0,n.index).replace(/\s+$/,""),i=t.slice(n.index+n[0].length).replace(/^\s*\n/,"");t=o+(o&&i.trim()?`
2
2
 
3
3
  `:"")+i}const e=t.trim();return e===""||e.startsWith("#!")&&!e.includes(`
4
4
  `)?"":t.replace(/\s+$/,"")+`
5
- `}async function w(r,t){if(m(t),!c(a(r,".git")))return{result:"skipped-no-git",hookPath:"",alterBlockEntfernt:!1};const e=a(r,".git","hooks","post-commit");let n="";try{n=await u(e,"utf-8")}catch{}const o=p(n);o!==null&&await f(e,o,"utf-8");const i=await h(r,t),l=o!==null;return{result:l&&i==="unchanged"?"upgraded":i,hookPath:e,alterBlockEntfernt:l}}export{s as BRAIN_WATCH_BLOCK_RE,w as installBrainWatchHook,p as ohneBrainWatchBlock};
5
+ `}async function y(r,t){if(p(t),!c(a(r,".git")))return{result:"skipped-no-git",hookPath:"",alterBlockEntfernt:!1};const e=a(m(r),"post-commit");let n="";try{n=await u(e,"utf-8")}catch{}const o=d(n);o!==null&&await f(e,o,"utf-8");const i=await h(r,t),s=o!==null;return{result:s&&i==="unchanged"?"upgraded":i,hookPath:e,alterBlockEntfernt:s}}export{l as BRAIN_WATCH_BLOCK_RE,y as installBrainWatchHook,d as ohneBrainWatchBlock};
@@ -1,8 +1,8 @@
1
- import{existsSync as d}from"node:fs";import{readFile as S,writeFile as r,chmod as s,mkdir as m}from"node:fs/promises";import{resolve as c}from"node:path";import{instanzIdFuerSkript as f}from"./git-ohne-shell.js";const l="v4",u=/(?:#!\/bin\/sh\n)?# cachly CLS[\s\S]*?\nexit 0\n?/;async function g(t,a,h){if(!d(c(t,".git")))return"skipped-no-git";const p=c(t,".git","hooks"),e=c(p,"post-commit");await m(p,{recursive:!0});const n=_(a);let i="";try{i=await S(e,"utf-8")}catch{}if(!i)return await r(e,n+`
2
- `,"utf-8"),await s(e,493).catch(()=>{}),"written";if(i.includes(`cachly CLS \u2014 Continuous Learning Stream ${l}`))return"unchanged";if(u.test(i)){const o=i.replace(u,n);return await r(e,o.endsWith(`
3
- `)?o:o+`
4
- `,"utf-8"),await s(e,493).catch(()=>{}),"upgraded"}return await r(e,i.trimEnd()+`
1
+ import{existsSync as f,statSync as h}from"node:fs";import{readFile as _,writeFile as p,chmod as u,mkdir as C}from"node:fs/promises";import{basename as l,dirname as d,resolve as o}from"node:path";import{gitLesen as y,instanzIdFuerSkript as L}from"./git-ohne-shell.js";const m="v4",S=/(?:#!\/bin\/sh\n)?# cachly CLS[\s\S]*?\nexit 0\n?/;function v(e){const t=o(e,".git","hooks");try{if(!h(o(e,".git")).isDirectory())return t}catch{return t}let s="";try{s=y(e,["rev-parse","--git-path","hooks"]).trim()}catch{return t}if(!s)return t;const n=o(e,s);return l(n)==="_"&&l(d(n))===".husky"?d(n):n}async function H(e,t,s){if(!f(o(e,".git")))return"skipped-no-git";const n=v(e),r=o(n,"post-commit");await C(n,{recursive:!0});const a=x(t);let i="";try{i=await _(r,"utf-8")}catch{}if(!i)return await p(r,a+`
2
+ `,"utf-8"),await u(r,493).catch(()=>{}),"written";if(i.includes(`cachly CLS \u2014 Continuous Learning Stream ${m}`))return"unchanged";if(S.test(i)){const c=i.replace(S,a);return await p(r,c.endsWith(`
3
+ `)?c:c+`
4
+ `,"utf-8"),await u(r,493).catch(()=>{}),"upgraded"}return await p(r,i.trimEnd()+`
5
5
 
6
- `+n+`
7
- `,"utf-8"),await s(e,493).catch(()=>{}),"appended"}const C="try{var cp=require('child_process'),pa=require('path'),fs=require('fs');var p={instance_id:process.env.CACHLY_BRAIN_INSTANCE_ID,source:'git_commit',payload:{message:process.env.CLS_MSG||'',sha:process.env.CLS_SHA||'',files:(process.env.CLS_FILES||'').split(',').filter(Boolean)}};var a=['-y','@cachly-dev/mcp-server@latest','cls-ingest',JSON.stringify(p)];var o={stdio:'ignore',timeout:30000};var d=pa.dirname(process.execPath);var c=[pa.join(d,'node_modules','npm','bin','npx-cli.js'),pa.join(d,'..','lib','node_modules','npm','bin','npx-cli.js')].filter(function(f){return fs.existsSync(f)})[0];if(c){cp.execFileSync(process.execPath,[c].concat(a),o)}else if(process.platform!=='win32'){cp.execFileSync('npx',a,o)}}catch(e){}";function _(t,a){return t=f(t),["#!/bin/sh",`# cachly CLS \u2014 Continuous Learning Stream ${l}`,"# Runs silently on every commit to keep your brain up to date.",`export CACHLY_BRAIN_INSTANCE_ID="${t}"`,'CLS_SHA=$(git rev-parse HEAD 2>/dev/null || echo "")',"CLS_MSG=$(git log -1 --pretty=%B 2>/dev/null | head -1 | cut -c1-200)","CLS_FILES=$(git diff-tree --no-commit-id -r --name-only HEAD 2>/dev/null | tr '\\n' ',' | sed 's/,$//')","export CLS_SHA CLS_MSG CLS_FILES",`node -e "${C}" 2>/dev/null &`,"exit 0"].join(`
8
- `)}export{u as CLS_BLOCK_RE,l as CLS_HOOK_VERSION,C as CLS_NODE_PROGRAM,_ as buildClsPostCommitHook,g as installClsPostCommitHook};
6
+ `+a+`
7
+ `,"utf-8"),await u(r,493).catch(()=>{}),"appended"}const g="try{var cp=require('child_process'),pa=require('path'),fs=require('fs');var p={instance_id:process.env.CACHLY_BRAIN_INSTANCE_ID,source:'git_commit',payload:{message:process.env.CLS_MSG||'',sha:process.env.CLS_SHA||'',files:(process.env.CLS_FILES||'').split(',').filter(Boolean)}};var a=['-y','@cachly-dev/mcp-server@latest','cls-ingest',JSON.stringify(p)];var o={stdio:'ignore',timeout:30000};var d=pa.dirname(process.execPath);var c=[pa.join(d,'node_modules','npm','bin','npx-cli.js'),pa.join(d,'..','lib','node_modules','npm','bin','npx-cli.js')].filter(function(f){return fs.existsSync(f)})[0];if(c){cp.execFileSync(process.execPath,[c].concat(a),o)}else if(process.platform!=='win32'){cp.execFileSync('npx',a,o)}}catch(e){}";function x(e,t){return e=L(e),["#!/bin/sh",`# cachly CLS \u2014 Continuous Learning Stream ${m}`,"# Runs silently on every commit to keep your brain up to date.",`export CACHLY_BRAIN_INSTANCE_ID="${e}"`,'CLS_SHA=$(git rev-parse HEAD 2>/dev/null || echo "")',"CLS_MSG=$(git log -1 --pretty=%B 2>/dev/null | head -1 | cut -c1-200)","CLS_FILES=$(git diff-tree --no-commit-id -r --name-only HEAD 2>/dev/null | tr '\\n' ',' | sed 's/,$//')","export CLS_SHA CLS_MSG CLS_FILES",`node -e "${g}" 2>/dev/null &`,"exit 0"].join(`
8
+ `)}export{S as CLS_BLOCK_RE,m as CLS_HOOK_VERSION,g as CLS_NODE_PROGRAM,x as buildClsPostCommitHook,v as gitHookOrdner,H as installClsPostCommitHook};
@@ -1,14 +1,14 @@
1
- import{ckgSlug as j}from"../ckg.js";import{safeJsonParse as x,darfHeraus as N}from"../utils.js";import{ersparteMinuten as P,zaehltAlsErsparnis as F}from"../wertbeitrag.js";import{findePaare as K}from"../zulassung-und-urteil.js";import{Vektorbestand as O}from"../bedeutung.js";import{doppelPaare as H}from"../doppel-kandidat.js";import{DOPPEL_SCHWELLE as U}from"../rangfolge-stellschrauben.js";import{sofortAntwortNeuesBrain as W}from"../leeres-brain.js";import{fuerWeitergabe as z}from"../schreibtor.js";function B(A){return N(A)&&!A.group}const te=new Set(["memory_consolidate","brain_diff","causal_trace","knowledge_decay","autopilot"]);async function ne(A,S,M,L){switch(A){case"memory_consolidate":{const{instance_id:l,dry_run:g=!1,stale_days:$=90}=S,m=await M(l),w=Date.now(),d=$*86400*1e3;let u=0;const _=[];do{const[n,e]=await m.scan(u,"MATCH","cachly:lesson:best:*","COUNT",200);u=parseInt(n),_.push(...e)}while(u!==0);if(_.length===0)return"\u{1F9E0} **Brain is empty** \u2014 no lessons to consolidate yet. Use `learn_from_attempts` after your next bug fix.";const c=new Map;for(const n of _){const e=await m.get(n);if(!e)continue;const s=x(e,null);s&&c.set(n,s)}const y=new O(0);await y.aktualisiere(m).catch(()=>{});const f=H([...c.values()].flatMap(n=>{const e=y.rohvektor(n.topic);return e?[{lektion:n,vektor:e}]:[]})),k=[...c.values()],b=K(k),h=b.filter(n=>n.beziehung==="widerspruch"),v=b.filter(n=>n.beziehung==="ersetzung"),t=[],o=new Map;for(const[n,e]of c){const s=o.get(e.topic)??[];s.push(n),o.set(e.topic,s)}for(const[n,e]of o)new Set(e.map(i=>c.get(i)?.outcome)).size>1&&t.push({topic:n,keys:e});const a=[];for(const[n,e]of c){const s=w-new Date(e.ts).getTime(),i=e.recall_count??0;s>d&&i===0&&a.push(n)}const r=0;if(!g)for(const n of a)await m.expire(n,86400*30);return[`\u{1F52C} **Memory Consolidation Report** ${g?"(dry run \u2014 no changes made)":"\u2705 Applied"}`,"",`\u{1F4CA} **Before:** ${_.length} lessons`,"",`\u{1F501} **Contradictions \u2014 exact topic match (old rule):** ${t.length}`,`\u{1F50E} **Same subject, admitted for judgement:** ${b.length} \u2192 contradiction ${h.length} \xB7 supersession ${v.length}`,...h.slice(0,5).map(n=>` \u2192 \`${n.a.topic}\` vs \`${n.b.topic}\` (${n.naehe.toFixed(2)}): ${n.grund}`),h.length>5?` \u2026 and ${h.length-5} more`:"",...v.slice(0,3).map(n=>` \u21BB \`${n.a.topic}\` \u2192 \`${n.b.topic}\`: ${n.grund}`),...t.slice(0,5).map(n=>` \u2192 \`${n.topic}\`: ${n.keys.length} conflicting entries (kept: success)`),t.length>5?` \u2026 and ${t.length-5} more`:"","",`\u267B\uFE0F **Possible duplicates \u2014 same meaning, different topic (cosine \u2265 ${U.toFixed(2)}, never merged):** ${f.length}`+(y.groesse===0?" (no vectors in this Brain, so nothing could be compared)":""),...f.slice(0,5).map(n=>` \u2192 \`${n.neu}\` \u2248 \`${n.alt}\` (${n.naehe.toFixed(2)})`),f.length>5?` \u2026 and ${f.length-5} more`:"",f.length>0?' If the newer one replaces the older, pass `ersetzt="<older topic>"` on its next `learn_from_attempts`.':"","",`\u{1F570}\uFE0F **Stale entries (${$}d, 0 recalls):** ${a.length}`+(a.length>0&&!g?" \u2192 set to expire in 30 days":""),"",`\u{1F4CA} **After:** ${_.length-r} lessons`,"",g?"\u{1F4A1} Re-run without dry_run=true to apply changes.":'\u2728 Brain consolidated. Run `brain_diff(since="1h")` to see the delta.'].filter(n=>n!=="").join(`
2
- `)}case"brain_diff":{const{instance_id:l,since:g="7d",format:$="summary"}=S,m=await M(l);let w;const d=g.match(/^(\d+)([dhm])$/);if(d){const e=parseInt(d[1]),s=d[2],i=s==="d"?864e5:s==="h"?36e5:6e4;w=Date.now()-e*i}else w=new Date(g).getTime()||Date.now()-7*864e5;let u=0;const _=[];do{const[e,s]=await m.scan(u,"MATCH","cachly:lesson:best:*","COUNT",200);u=parseInt(e),_.push(...s)}while(u!==0);const c=[],y=[],f=[],k=_.length;for(const e of _){const s=await m.get(e);if(s){const i=x(s,null);if(!i)continue;if(new Date(i.ts).getTime()>=w){const T=`cachly:lesson:history:${i.topic}`;await m.llen(T)<=1?c.push(i):y.push(i)}(i.recall_count??0)>0&&f.push(i)}}const h=[`\u{1F4CA} **Brain Diff** \u2014 ${d?`last ${g}`:new Date(w).toLocaleDateString("de-DE")}`,"",`Total lessons in brain: **${k}**`,"",`\u2705 **New** (${c.length}):`,...c.slice(0,$==="detailed"?20:5).map(e=>` + \`${e.topic}\` \u2014 ${e.outcome} ${e.severity==="critical"?"\u{1F534}":e.severity==="major"?"\u{1F7E0}":"\u{1F7E2}"}`),c.length>5&&$==="summary"?` \u2026 and ${c.length-5} more`:"","",`\u{1F504} **Updated** (${y.length}):`,...y.slice(0,$==="detailed"?20:5).map(e=>` ~ \`${e.topic}\` \u2014 now: ${e.outcome}`),y.length>5&&$==="summary"?` \u2026 and ${y.length-5} more`:"","",`\u{1F50D} **Active** (recalled at least once): ${f.length}`,""].filter(e=>e!==""),v=[],t=m.scanStream({match:"cachly:ckg:node:resolution-*",count:100});await new Promise((e,s)=>{t.on("data",i=>v.push(...i)),t.on("end",e),t.on("error",s)});const o=[];for(const e of v){const s=await m.get(e);if(s){const i=x(s,null);i?.ts&&new Date(i.ts).getTime()>=w&&o.push({topic:i.topic??e,resolution:i.resolution??"unknown",ts:i.ts})}}if(o.length>0){h.push(`\u{1F5F3}\uFE0F **MADC Resolutions** (${o.length} contested beliefs resolved):`);for(const e of o.slice(0,5)){const s=e.resolution==="unanimous_success"?"\u2705":e.resolution==="unanimous_failure"?"\u274C":"\u26A0\uFE0F";h.push(` ${s} \`${e.topic}\` \u2192 ${e.resolution}`)}h.push("")}const a=new Set(y.concat(f).map(e=>e.topic.split(":")[0])),r=[...new Set(c.map(e=>e.topic.split(":")[0]))].filter(e=>!a.has(e));r.length>0&&h.push(`\u{1F331} **New domains bootstrapped:** ${r.map(e=>`\`${e}\``).join(", ")}`,"");const n=(await m.lrange("cachly:fedbrain:federations",-20,-1)).map(e=>x(e,null)).filter(e=>e!==null&&new Date(e.transferred_at).getTime()>=w);if(n.length>0){h.push(`\u{1F9E0} **FedBrain transfers received (${n.length}):**`);for(const e of n.slice(0,3))h.push(` \u{1F4E5} domain \`${e.domain}\` from \`${e.source.slice(0,16)}\u2026\` \u2014 ${e.nodes} nodes, ${e.edges} edges`);h.push("")}return h.push("\u{1F4A1} Run `memory_consolidate` to merge duplicates \xB7 `knowledge_decay` to see confidence scores."),h.join(`
3
- `)}case"causal_trace":{const{instance_id:l,problem:g,max_depth:$=5,tags:m=[]}=S,w=await W(l,L,`\u{1F50D} **Causal Trace: "${g}"**
1
+ import{ckgSlug as L}from"../ckg.js";import{safeJsonParse as x,darfHeraus as N}from"../utils.js";import{ersparteMinuten as F,zaehltAlsErsparnis as K}from"../wertbeitrag.js";import{findePaare as O}from"../zulassung-und-urteil.js";import{Vektorbestand as H}from"../bedeutung.js";import{doppelPaare as U}from"../doppel-kandidat.js";import{DOPPEL_SCHWELLE as W}from"../rangfolge-stellschrauben.js";import{sofortAntwortNeuesBrain as z}from"../leeres-brain.js";import{fuerWeitergabe as G}from"../schreibtor.js";import{kappeAnfrage as V,trefferIstStark as q}from"../pflichtfelder.js";function B(M){return N(M)&&!M.group}const ae=new Set(["memory_consolidate","brain_diff","causal_trace","knowledge_decay","autopilot"]);async function ie(M,D,R,P){switch(M){case"memory_consolidate":{const{instance_id:d,dry_run:_=!1,stale_days:y=90}=D,m=await R(d),f=Date.now(),k=y*86400*1e3;let c=0;const u=[];do{const[t,e]=await m.scan(c,"MATCH","cachly:lesson:best:*","COUNT",200);c=parseInt(t),u.push(...e)}while(c!==0);if(u.length===0)return"\u{1F9E0} **Brain is empty** \u2014 no lessons to consolidate yet. Use `learn_from_attempts` after your next bug fix.";const l=new Map;for(const t of u){const e=await m.get(t);if(!e)continue;const o=x(e,null);o&&l.set(t,o)}const g=new H(0);await g.aktualisiere(m).catch(()=>{});const w=U([...l.values()].flatMap(t=>{const e=g.rohvektor(t.topic);return e?[{lektion:t,vektor:e}]:[]})),$=[...l.values()],b=O($),p=b.filter(t=>t.beziehung==="widerspruch"),S=b.filter(t=>t.beziehung==="ersetzung"),a=[],n=new Map;for(const[t,e]of l){const o=n.get(e.topic)??[];o.push(t),n.set(e.topic,o)}for(const[t,e]of n)new Set(e.map(i=>l.get(i)?.outcome)).size>1&&a.push({topic:t,keys:e});const s=[];for(const[t,e]of l){const o=f-new Date(e.ts).getTime(),i=e.recall_count??0;o>k&&i===0&&s.push(t)}const r=0;if(!_)for(const t of s)await m.expire(t,86400*30);return[`\u{1F52C} **Memory Consolidation Report** ${_?"(dry run \u2014 no changes made)":"\u2705 Applied"}`,"",`\u{1F4CA} **Before:** ${u.length} lessons`,"",`\u{1F501} **Contradictions \u2014 exact topic match (old rule):** ${a.length}`,`\u{1F50E} **Same subject, admitted for judgement:** ${b.length} \u2192 contradiction ${p.length} \xB7 supersession ${S.length}`,...p.slice(0,5).map(t=>` \u2192 \`${t.a.topic}\` vs \`${t.b.topic}\` (${t.naehe.toFixed(2)}): ${t.grund}`),p.length>5?` \u2026 and ${p.length-5} more`:"",...S.slice(0,3).map(t=>` \u21BB \`${t.a.topic}\` \u2192 \`${t.b.topic}\`: ${t.grund}`),...a.slice(0,5).map(t=>` \u2192 \`${t.topic}\`: ${t.keys.length} conflicting entries (kept: success)`),a.length>5?` \u2026 and ${a.length-5} more`:"","",`\u267B\uFE0F **Possible duplicates \u2014 same meaning, different topic (cosine \u2265 ${W.toFixed(2)}, never merged):** ${w.length}`+(g.groesse===0?" (no vectors in this Brain, so nothing could be compared)":""),...w.slice(0,5).map(t=>` \u2192 \`${t.neu}\` \u2248 \`${t.alt}\` (${t.naehe.toFixed(2)})`),w.length>5?` \u2026 and ${w.length-5} more`:"",w.length>0?' If the newer one replaces the older, pass `ersetzt="<older topic>"` on its next `learn_from_attempts`.':"","",`\u{1F570}\uFE0F **Stale entries (${y}d, 0 recalls):** ${s.length}`+(s.length>0&&!_?" \u2192 set to expire in 30 days":""),"",`\u{1F4CA} **After:** ${u.length-r} lessons`,"",_?"\u{1F4A1} Re-run without dry_run=true to apply changes.":'\u2728 Brain consolidated. Run `brain_diff(since="1h")` to see the delta.'].filter(t=>t!=="").join(`
2
+ `)}case"brain_diff":{const{instance_id:d,since:_="7d",format:y="summary"}=D,m=await R(d);let f;const k=_.match(/^(\d+)([dhm])$/);if(k){const e=parseInt(k[1]),o=k[2],i=o==="d"?864e5:o==="h"?36e5:6e4;f=Date.now()-e*i}else f=new Date(_).getTime()||Date.now()-7*864e5;let c=0;const u=[];do{const[e,o]=await m.scan(c,"MATCH","cachly:lesson:best:*","COUNT",200);c=parseInt(e),u.push(...o)}while(c!==0);const l=[],g=[],w=[],$=u.length;for(const e of u){const o=await m.get(e);if(o){const i=x(o,null);if(!i)continue;if(new Date(i.ts).getTime()>=f){const T=`cachly:lesson:history:${i.topic}`;await m.llen(T)<=1?l.push(i):g.push(i)}(i.recall_count??0)>0&&w.push(i)}}const p=[`\u{1F4CA} **Brain Diff** \u2014 ${k?`last ${_}`:new Date(f).toLocaleDateString("de-DE")}`,"",`Total lessons in brain: **${$}**`,"",`\u2705 **New** (${l.length}):`,...l.slice(0,y==="detailed"?20:5).map(e=>` + \`${e.topic}\` \u2014 ${e.outcome} ${e.severity==="critical"?"\u{1F534}":e.severity==="major"?"\u{1F7E0}":"\u{1F7E2}"}`),l.length>5&&y==="summary"?` \u2026 and ${l.length-5} more`:"","",`\u{1F504} **Updated** (${g.length}):`,...g.slice(0,y==="detailed"?20:5).map(e=>` ~ \`${e.topic}\` \u2014 now: ${e.outcome}`),g.length>5&&y==="summary"?` \u2026 and ${g.length-5} more`:"","",`\u{1F50D} **Active** (recalled at least once): ${w.length}`,""].filter(e=>e!==""),S=[],a=m.scanStream({match:"cachly:ckg:node:resolution-*",count:100});await new Promise((e,o)=>{a.on("data",i=>S.push(...i)),a.on("end",e),a.on("error",o)});const n=[];for(const e of S){const o=await m.get(e);if(o){const i=x(o,null);i?.ts&&new Date(i.ts).getTime()>=f&&n.push({topic:i.topic??e,resolution:i.resolution??"unknown",ts:i.ts})}}if(n.length>0){p.push(`\u{1F5F3}\uFE0F **MADC Resolutions** (${n.length} contested beliefs resolved):`);for(const e of n.slice(0,5)){const o=e.resolution==="unanimous_success"?"\u2705":e.resolution==="unanimous_failure"?"\u274C":"\u26A0\uFE0F";p.push(` ${o} \`${e.topic}\` \u2192 ${e.resolution}`)}p.push("")}const s=new Set(g.concat(w).map(e=>e.topic.split(":")[0])),r=[...new Set(l.map(e=>e.topic.split(":")[0]))].filter(e=>!s.has(e));r.length>0&&p.push(`\u{1F331} **New domains bootstrapped:** ${r.map(e=>`\`${e}\``).join(", ")}`,"");const t=(await m.lrange("cachly:fedbrain:federations",-20,-1)).map(e=>x(e,null)).filter(e=>e!==null&&new Date(e.transferred_at).getTime()>=f);if(t.length>0){p.push(`\u{1F9E0} **FedBrain transfers received (${t.length}):**`);for(const e of t.slice(0,3))p.push(` \u{1F4E5} domain \`${e.domain}\` from \`${e.source.slice(0,16)}\u2026\` \u2014 ${e.nodes} nodes, ${e.edges} edges`);p.push("")}return p.push("\u{1F4A1} Run `memory_consolidate` to merge duplicates \xB7 `knowledge_decay` to see confidence scores."),p.join(`
3
+ `)}case"causal_trace":{const{instance_id:d,problem:_,max_depth:y=5,tags:m=[]}=D,f=V(_),k=await z(d,P,`\u{1F50D} **Causal Trace: "${f}"**
4
4
 
5
- No matching lessons found in brain.`);if(w)return w;const d=await M(l),u=g.toLowerCase().replace(/[^a-z0-9\s\-_:]/g," ").split(/\s+/).filter(o=>o.length>2),_={critical:"\u{1F534}",major:"\u{1F7E0}",minor:"\u{1F7E1}"},c=[];try{for(const o of u.slice(0,4)){const a=await d.smembers(`cachly:ckg:idx:from:${j(o)}`),r=await d.smembers(`cachly:ckg:idx:to:${j(o)}`),p=[],n=d.scanStream({match:`cachly:ckg:node:*${o}*`,count:50});await new Promise((e,s)=>{n.on("data",i=>p.push(...i)),n.on("end",e),n.on("error",s)});for(const e of p.slice(0,10)){const s=await d.get(e);if(!s)continue;const i=x(s,null);if(!i)continue;const D=await d.smembers(`cachly:ckg:idx:from:${i.id}`);for(const T of D.slice(0,20)){const R=await d.get(T);if(!R)continue;const C=x(R,null);if(!C||C.edgeType!=="fixes"&&C.edgeType!=="requires")continue;const I=await d.get(`cachly:lesson:best:${C.from.replace(/-/g,":").replace(/^fix:/,"fix:")}`),E=I?x(I,null)??void 0:void 0;c.push({conceptId:i.id,edge:C,lesson:E&&B(E)?E:void 0})}}for(const e of[...a,...r].slice(0,20)){const s=await d.get(e);if(!s)continue;const i=x(s,null);if(!i)continue;const D=await d.get(`cachly:lesson:best:${i.from}`),T=D?x(D,null)??void 0:void 0;c.push({conceptId:i.from,edge:i,lesson:T&&B(T)?T:void 0})}}}catch{}const y=new Set,f=c.filter(o=>{const a=`${o.edge.from}:${o.edge.edgeType}:${o.edge.to}`;return y.has(a)?!1:(y.add(a),!0)}).sort((o,a)=>a.edge.confidence-o.edge.confidence).slice(0,$);let k=0;const b=[];do{const[o,a]=await d.scan(k,"MATCH","cachly:lesson:best:*","COUNT",200);k=parseInt(o),b.push(...a)}while(k!==0);const h=[];for(const o of b){const a=await d.get(o);if(a){const r=x(a,null);if(!r||!B(r)||m.length>0&&!(r.tags??[]).some(e=>m.includes(e)))continue;const p=[r.topic,r.what_failed??"",r.what_worked??"",r.context??""].join(" ").toLowerCase(),n=u.reduce((e,s)=>e+(p.includes(s)?1:0),0);n>0&&h.push({score:n,lesson:r,key:o})}}h.sort((o,a)=>a.score-o.score);const v=h.slice(0,$);if(v.length===0&&f.length===0)return[`\u{1F50D} **Causal Trace: "${g}"**`,"","No matching lessons found in brain.","","\u{1F4A1} After you solve this, call:","```","learn_from_attempts(",` instance_id = "${l}",`,` topic = "fix:${u[0]??"issue"}",`,' outcome = "success",',' what_worked = "...",',` what_failed = "${g}",`,")","```"].join(`
6
- `);const t=[`\u{1F50D} **Causal Trace: "${g}"**`,""];if(f.length>0){t.push("### \u{1F578}\uFE0F CKG Graph (confidence-ranked)");for(const o of f){const a=Math.round(o.edge.confidence*100),r="\u2593".repeat(Math.round(a/10))+"\u2591".repeat(10-Math.round(a/10));t.push(` ${o.edge.from} **\u2192[${o.edge.edgeType}]\u2192** ${o.edge.to}`),t.push(` ${r} ${a}% confidence (${o.edge.successes}/${o.edge.trials} confirmed)`),o.lesson?.what_worked&&t.push(` \u2705 Fix: ${o.lesson.what_worked.slice(0,150)}`),t.push("")}}if(v.length>0){t.push(f.length>0?`### \u{1F4DA} Text Search (${v.length} related lessons)`:`Found **${v.length}** related lessons. Reconstructed causal chain:`,"");const o=v.filter(p=>p.lesson.outcome!=="success"),a=v.filter(p=>p.lesson.outcome==="success");o.length>0&&(t.push("**Root causes & failure chain:**"),o.forEach((p,n)=>{const e=p.lesson,s=_[e.severity??"minor"]??"\u{1F7E1}";t.push(`${n===0?" Root:":" \u2192 :"} ${s} \`${e.topic}\``),e.what_failed&&t.push(` \u21B3 ${e.what_failed.slice(0,120)}`)}),t.push("")),a.length>0&&(t.push("**Solutions that worked before:**"),a.forEach((p,n)=>{const e=p.lesson,s=new Date(e.ts).toLocaleDateString("de-DE");t.push(` ${n+1}. \u2705 \`${e.topic}\` \u2014 ${s} \xB7 in ${e.recall_count??0} answers`),e.what_worked&&t.push(` ${e.what_worked.slice(0,200)}`)}),t.push(""));const r=a[0]?.lesson;if(r?.what_worked){t.push("**\u26A1 Most likely fix:**"),t.push("```"),t.push(r.what_worked.slice(0,500)),t.push("```"),t.push("");const p=F(r)?P(r,"trace"):0;p>0&&d.incrbyfloat(`cachly:stats:time_saved_mins:${l}`,p).catch(()=>{})}}return t.push(`\u{1F4A1} After applying: \`learn_from_attempts(topic="fix:${u[0]??"issue"}", outcome="success", ...)\``),f.length>0&&t.push(`\u{1F578}\uFE0F Explore graph: \`ckg_inspect(concept="${u[0]??"fix"}")\``),t.join(`
7
- `)}case"knowledge_decay":{let f=function(t){const o=Math.round(t/10);return"\u2588".repeat(o)+"\u2591".repeat(10-o)+` ${t}%`};const{instance_id:l,min_age_days:g=0,show_top:$=20}=S,m=await M(l),w=Date.now(),d=g*864e5;let u=0;const _=[];do{const[t,o]=await m.scan(u,"MATCH","cachly:lesson:best:*","COUNT",200);u=parseInt(t),_.push(...o)}while(u!==0);const c=[];for(const t of _){const o=await m.get(t);if(o){const a=x(o,null);if(!a)continue;const r=w-new Date(a.ts).getTime();if(r<d)continue;const p=Math.floor(r/864e5),n=a.recall_count??0,e=Math.max(0,p-7),s=Math.max(5,100-e),i=Math.min(50,n*5),D=a.outcome==="failure"?-20:0,T=Math.min(100,Math.max(0,s+i+D));c.push({topic:a.topic,confidence:T,age_days:p,recalls:n,outcome:a.outcome})}}c.sort((t,o)=>t.confidence-o.confidence);const y=c.slice(0,$),k=c.length>0?Math.round(c.reduce((t,o)=>t+o.confidence,0)/c.length):0,b=c.filter(t=>t.confidence<30).length,h=c.filter(t=>t.confidence>=70).length;return[`\u{1F9EA} **Knowledge Decay Report** \u2014 ${c.length} lessons`,"",`Average confidence: **${f(k)}**`,`\u{1F534} Critical (<30%): ${b} \u{1F7E2} Healthy (\u226570%): ${h}`,"","Lowest confidence lessons (fix these first):","",...y.map((t,o)=>`${(o+1).toString().padStart(2)}. \`${t.topic}\`
8
- ${f(t.confidence)} \xB7 ${t.age_days}d old \xB7 ${t.recalls} recalls \xB7 ${t.outcome}`),"",c.length>$?`\u2026 and ${c.length-$} more lessons`:"","",b>0?`\u26A0\uFE0F ${b} lessons are critically stale. Validate them and re-run \`learn_from_attempts\` with updated findings.`:"\u2705 Brain confidence is healthy overall.","","\u{1F4A1} Run `memory_consolidate` to prune stale entries \xB7 `causal_trace` to find root causes."].filter(t=>t!=="").join(`
9
- `)}case"autopilot":{const{instance_id:l,editor:g="claude",project_name:$="this project",style:m="full"}=S,w=z({editor:String(g),project_name:String($)},"the instruction file (CLAUDE.md)");if(!w.ok)return w.meldung;const d=(b,h)=>b.replace(/[\p{C}\s]+/gu," ").trim().slice(0,h),u=d(w.felder.editor,30)||"claude",_=d(w.felder.project_name,80)||"this project",c=`## Cachly AI Brain \u2014 Autopilot
5
+ No matching lessons found in brain.`);if(k)return k;const c=await R(d),u=f.toLowerCase().replace(/[^a-z0-9\s\-_:]/g," ").split(/\s+/).filter(s=>s.length>2),l={critical:"\u{1F534}",major:"\u{1F7E0}",minor:"\u{1F7E1}"},g=[];try{for(const s of u.slice(0,4)){const r=await c.smembers(`cachly:ckg:idx:from:${L(s)}`),h=await c.smembers(`cachly:ckg:idx:to:${L(s)}`),t=[],e=c.scanStream({match:`cachly:ckg:node:*${s}*`,count:50});await new Promise((o,i)=>{e.on("data",v=>t.push(...v)),e.on("end",o),e.on("error",i)});for(const o of t.slice(0,10)){const i=await c.get(o);if(!i)continue;const v=x(i,null);if(!v)continue;const T=await c.smembers(`cachly:ckg:idx:from:${v.id}`);for(const C of T.slice(0,20)){const I=await c.get(C);if(!I)continue;const A=x(I,null);if(!A||A.edgeType!=="fixes"&&A.edgeType!=="requires")continue;const j=await c.get(`cachly:lesson:best:${A.from.replace(/-/g,":").replace(/^fix:/,"fix:")}`),E=j?x(j,null)??void 0:void 0;g.push({conceptId:v.id,edge:A,lesson:E&&B(E)?E:void 0})}}for(const o of[...r,...h].slice(0,20)){const i=await c.get(o);if(!i)continue;const v=x(i,null);if(!v)continue;const T=await c.get(`cachly:lesson:best:${v.from}`),C=T?x(T,null)??void 0:void 0;g.push({conceptId:v.from,edge:v,lesson:C&&B(C)?C:void 0})}}}catch{}const w=new Set,$=g.filter(s=>{const r=`${s.edge.from}:${s.edge.edgeType}:${s.edge.to}`;return w.has(r)?!1:(w.add(r),!0)}).sort((s,r)=>r.edge.confidence-s.edge.confidence).slice(0,y);let b=0;const p=[];do{const[s,r]=await c.scan(b,"MATCH","cachly:lesson:best:*","COUNT",200);b=parseInt(s),p.push(...r)}while(b!==0);const S=[];for(const s of p){const r=await c.get(s);if(r){const h=x(r,null);if(!h||!B(h)||m.length>0&&!(h.tags??[]).some(o=>m.includes(o)))continue;const t=[h.topic,h.what_failed??"",h.what_worked??"",h.context??""].join(" ").toLowerCase(),e=u.reduce((o,i)=>o+(t.includes(i)?1:0),0);e>0&&S.push({score:e,lesson:h,key:s})}}S.sort((s,r)=>r.score-s.score);const a=S.slice(0,y);if(a.length===0&&$.length===0)return[`\u{1F50D} **Causal Trace: "${f}"**`,"","No matching lessons found in brain.","","\u{1F4A1} After you solve this, call:","```","learn_from_attempts(",` instance_id = "${d}",`,` topic = "fix:${u[0]??"issue"}",`,' outcome = "success",',' what_worked = "...",',` what_failed = "${f}",`,")","```"].join(`
6
+ `);const n=[`\u{1F50D} **Causal Trace: "${f}"**`,""];if($.length>0){n.push("### \u{1F578}\uFE0F CKG Graph (confidence-ranked)");for(const s of $){const r=Math.round(s.edge.confidence*100),h="\u2593".repeat(Math.round(r/10))+"\u2591".repeat(10-Math.round(r/10));n.push(` ${s.edge.from} **\u2192[${s.edge.edgeType}]\u2192** ${s.edge.to}`),n.push(` ${h} ${r}% confidence (${s.edge.successes}/${s.edge.trials} confirmed)`),s.lesson?.what_worked&&n.push(` \u2705 Fix: ${s.lesson.what_worked.slice(0,150)}`),n.push("")}}if(a.length>0){n.push($.length>0?`### \u{1F4DA} Text Search (${a.length} related lessons)`:`Found **${a.length}** related lessons. Reconstructed causal chain:`,"");const s=a.filter(t=>t.lesson.outcome!=="success"),r=a.filter(t=>t.lesson.outcome==="success");s.length>0&&(n.push("**Root causes & failure chain:**"),s.forEach((t,e)=>{const o=t.lesson,i=l[o.severity??"minor"]??"\u{1F7E1}";n.push(`${e===0?" Root:":" \u2192 :"} ${i} \`${o.topic}\``),o.what_failed&&n.push(` \u21B3 ${o.what_failed.slice(0,120)}`)}),n.push("")),r.length>0&&(n.push("**Solutions that worked before:**"),r.forEach((t,e)=>{const o=t.lesson,i=new Date(o.ts).toLocaleDateString("de-DE");n.push(` ${e+1}. \u2705 \`${o.topic}\` \u2014 ${i} \xB7 in ${o.recall_count??0} answers`),o.what_worked&&n.push(` ${o.what_worked.slice(0,200)}`)}),n.push(""));const h=r[0]?.lesson;if(h?.what_worked){const t=q(r[0].score,u);n.push(t?"**\u26A1 Most likely fix:**":`**Closest solution (weak match: ${r[0].score} of ${new Set(u).size} words \u2014 check that it fits before using it):**`),n.push("```"),n.push(h.what_worked.slice(0,500)),n.push("```"),n.push("");const e=K(h)?F(h,"trace"):0;e>0&&c.incrbyfloat(`cachly:stats:time_saved_mins:${d}`,e).catch(()=>{})}}return n.push(`\u{1F4A1} After applying: \`learn_from_attempts(topic="fix:${u[0]??"issue"}", outcome="success", ...)\``),$.length>0&&n.push(`\u{1F578}\uFE0F Explore graph: \`ckg_inspect(concept="${u[0]??"fix"}")\``),n.join(`
7
+ `)}case"knowledge_decay":{let w=function(a){const n=Math.round(a/10);return"\u2588".repeat(n)+"\u2591".repeat(10-n)+` ${a}%`};const{instance_id:d,min_age_days:_=0,show_top:y=20}=D,m=await R(d),f=Date.now(),k=_*864e5;let c=0;const u=[];do{const[a,n]=await m.scan(c,"MATCH","cachly:lesson:best:*","COUNT",200);c=parseInt(a),u.push(...n)}while(c!==0);const l=[];for(const a of u){const n=await m.get(a);if(n){const s=x(n,null);if(!s)continue;const r=f-new Date(s.ts).getTime();if(r<k)continue;const h=Math.floor(r/864e5),t=s.recall_count??0,e=Math.max(0,h-7),o=Math.max(5,100-e),i=Math.min(50,t*5),v=s.outcome==="failure"?-20:0,T=Math.min(100,Math.max(0,o+i+v));l.push({topic:s.topic,confidence:T,age_days:h,recalls:t,outcome:s.outcome})}}l.sort((a,n)=>a.confidence-n.confidence);const g=l.slice(0,y),$=l.length>0?Math.round(l.reduce((a,n)=>a+n.confidence,0)/l.length):0,b=l.filter(a=>a.confidence<30).length,p=l.filter(a=>a.confidence>=70).length;return[`\u{1F9EA} **Knowledge Decay Report** \u2014 ${l.length} lessons`,"",`Average confidence: **${w($)}**`,`\u{1F534} Critical (<30%): ${b} \u{1F7E2} Healthy (\u226570%): ${p}`,"","Lowest confidence lessons (fix these first):","",...g.map((a,n)=>`${(n+1).toString().padStart(2)}. \`${a.topic}\`
8
+ ${w(a.confidence)} \xB7 ${a.age_days}d old \xB7 ${a.recalls} recalls \xB7 ${a.outcome}`),"",l.length>y?`\u2026 and ${l.length-y} more lessons`:"","",b>0?`\u26A0\uFE0F ${b} lessons are critically stale. Validate them and re-run \`learn_from_attempts\` with updated findings.`:"\u2705 Brain confidence is healthy overall.","","\u{1F4A1} Run `memory_consolidate` to prune stale entries \xB7 `causal_trace` to find root causes."].filter(a=>a!=="").join(`
9
+ `)}case"autopilot":{const{instance_id:d,editor:_="claude",project_name:y="this project",style:m="full"}=D,f=G({editor:String(_),project_name:String(y)},"the instruction file (CLAUDE.md)");if(!f.ok)return f.meldung;const k=(b,p)=>b.replace(/[\p{C}\s]+/gu," ").trim().slice(0,p),c=k(f.felder.editor,30)||"claude",u=k(f.felder.project_name,80)||"this project",l=`## Cachly AI Brain \u2014 Autopilot
10
10
 
11
- **Instance:** \`${l}\`
11
+ **Instance:** \`${d}\`
12
12
 
13
13
  > **Where your data goes:** these calls read/write *your own* Brain instance
14
14
  > (the ID above) \u2014 your infrastructure, EU-hosted, under your control. Nothing
@@ -19,12 +19,12 @@ No matching lessons found in brain.`);if(w)return w;const d=await M(l),u=g.toLow
19
19
  > Sessions are fully automatic. The Brain starts when you call any tool and saves a summary when you close.
20
20
 
21
21
  ### Brain hooks \u2014 run these automatically (safe to skip if a step doesn't apply):
22
- - **Window opens** \u2192 call \`session_start(instance_id="${l}", focus="<today's goal>")\`
23
- - **Bug fixed / deployed / discovered** \u2192 call \`learn_from_attempts(instance_id="${l}", topic="fix:<area>", outcome="success", what_worked="...")\`
24
- - **Window closes** \u2192 call \`session_end(instance_id="${l}", summary="...", files_changed=[...])\`
25
- `,y=`## Cachly AI Brain \u2014 Autopilot for ${_}
22
+ - **Window opens** \u2192 call \`session_start(instance_id="${d}", focus="<today's goal>")\`
23
+ - **Bug fixed / deployed / discovered** \u2192 call \`learn_from_attempts(instance_id="${d}", topic="fix:<area>", outcome="success", what_worked="...")\`
24
+ - **Window closes** \u2192 call \`session_end(instance_id="${d}", summary="...", files_changed=[...])\`
25
+ `,g=`## Cachly AI Brain \u2014 Autopilot for ${u}
26
26
 
27
- **Instance:** \`${l}\`
27
+ **Instance:** \`${d}\`
28
28
 
29
29
  > **What this is & where your data goes:** the calls below read and write to
30
30
  > *your own* Cachly Brain instance (the ID above) \u2014 your infrastructure,
@@ -42,7 +42,7 @@ No matching lessons found in brain.`);if(w)return w;const d=await M(l),u=g.toLow
42
42
  ### Rule 1 \u2014 Session Start (FIRST thing in every window)
43
43
  \`\`\`
44
44
  session_start(
45
- instance_id = "${l}",
45
+ instance_id = "${d}",
46
46
  focus = "<what you plan to work on today>",
47
47
  )
48
48
  \`\`\`
@@ -52,7 +52,7 @@ Returns: last session summary, handoff tasks, recent lessons, open failures.
52
52
  **After EVERY** bug fix, deployment, or technical discovery \u2014 call immediately:
53
53
  \`\`\`
54
54
  learn_from_attempts(
55
- instance_id = "${l}",
55
+ instance_id = "${d}",
56
56
  topic = "category:keyword",
57
57
  outcome = "success" | "failure" | "partial",
58
58
  what_worked = "exact command or approach",
@@ -72,7 +72,7 @@ learn_from_attempts(
72
72
  ### Rule 3 \u2014 Session End (LAST thing before closing)
73
73
  \`\`\`
74
74
  session_end(
75
- instance_id = "${l}",
75
+ instance_id = "${d}",
76
76
  summary = "What was accomplished (2-3 sentences)",
77
77
  files_changed = ["list", "of", "changed", "files"],
78
78
  lessons_learned = <number of learn_from_attempts calls>,
@@ -82,7 +82,7 @@ session_end(
82
82
  ### Rule 4 \u2014 Before any non-trivial task
83
83
  \`\`\`
84
84
  smart_recall(
85
- instance_id = "${l}",
85
+ instance_id = "${d}",
86
86
  query = "<describe what you are about to do>",
87
87
  )
88
88
  \`\`\`
@@ -93,13 +93,13 @@ smart_recall(
93
93
 
94
94
  | When | Call |
95
95
  |---|---|
96
- | Brain feeling cluttered | \`memory_consolidate(instance_id="${l}")\` |
97
- | Weekly review | \`brain_diff(instance_id="${l}", since="7d")\` |
98
- | Weird bug, no idea why | \`causal_trace(instance_id="${l}", problem="<symptom>")\` |
99
- | Before big refactor | \`knowledge_decay(instance_id="${l}")\` |
96
+ | Brain feeling cluttered | \`memory_consolidate(instance_id="${d}")\` |
97
+ | Weekly review | \`brain_diff(instance_id="${d}", since="7d")\` |
98
+ | Weird bug, no idea why | \`causal_trace(instance_id="${d}", problem="<symptom>")\` |
99
+ | Before big refactor | \`knowledge_decay(instance_id="${d}")\` |
100
100
 
101
101
  ---
102
102
 
103
103
  *Cachly v0.6 \xB7 Generated ${new Date().toISOString().slice(0,10)}*
104
- `,f=m==="minimal"?c:y,k=u==="copilot"?".github/copilot-instructions.md":u==="continue"?".continue/cachly-autopilot.md":"CLAUDE.md";return[`\u{1F916} **Autopilot instructions generated** for **${u==="all"?"all editors":u}**`,"",`**File:** \`${k}\` \u2014 create it, or APPEND to your existing one`,"","```markdown",f,"```","",`**How to apply** (\`>>\` appends \u2014 an existing ${k} keeps every line you wrote):`,"```bash",`cat >> ${k} << 'EOF'`,f,"EOF","```","",`\u2728 Once this file is in place, **${u==="copilot"?"GitHub Copilot":u==="continue"?"Continue.dev":"Claude/Cursor/Windsurf"}** will manage the Brain automatically \u2014 no manual calls needed, ever.`].join(`
105
- `)}default:return null}}export{te as ADVANCED_TOOL_NAMES,ne as handleAdvancedTool};
104
+ `,w=m==="minimal"?l:g,$=c==="copilot"?".github/copilot-instructions.md":c==="continue"?".continue/cachly-autopilot.md":"CLAUDE.md";return[`\u{1F916} **Autopilot instructions generated** for **${c==="all"?"all editors":c}**`,"",`**File:** \`${$}\` \u2014 create it, or APPEND to your existing one`,"","```markdown",w,"```","",`**How to apply** (\`>>\` appends \u2014 an existing ${$} keeps every line you wrote):`,"```bash",`cat >> ${$} << 'EOF'`,w,"EOF","```","",`\u2728 Once this file is in place, **${c==="copilot"?"GitHub Copilot":c==="continue"?"Continue.dev":"Claude/Cursor/Windsurf"}** will manage the Brain automatically \u2014 no manual calls needed, ever.`].join(`
105
+ `)}default:return null}}export{ae as ADVANCED_TOOL_NAMES,ie as handleAdvancedTool};